Ext.ns('AIR2.Drawer');
/***************
 * AIR2 Drawer Component
 *
 * Component to dock in the lower-right hand corner of the screen, sliding open
 * to allow items to be dragged into Bins.
 *
 * @class AIR2.Drawer
 * @extends Ext.Component
 *
 */
AIR2.Drawer = function() {
    // get drawer STATE parameters (if any)
    this.currView = AIR2.Drawer.STATE.get('view');
    if (!this.currView) {
        this.currView = 'sm'; //'sm', 'lg', 'si'
        AIR2.Drawer.STATE.set('view', this.currView);
    }
    var initOpen = AIR2.Drawer.STATE.get('open') || false;
    var inlineParams = AIR2.Drawer.STATE.get('params');
    var inlineData = AIR2.BINDATA;
    var inlineBin = AIR2.BINBASE;

    AIR2.Drawer.superclass.constructor.call(this, {});

    // render/setup drawer controls
    this.controls = new Ext.Toolbar({
        defaults: {
            xtype: 'air2button',
            air2type: 'CLEAR',
            scope: this
        },
        items: ['->', {
            iconCls: 'air2-icon-bin-dock',
            handler: this.slideShut
        },{
            enableToggle: true,
            allowDepress: false,
            toggleGroup: 'air2-drawer-controls',
            iconCls: 'air2-icon-bin-small',
            pressed: this.currView == 'sm',
            toggleHandler: function(btn, state) {
                if (state) this.transitionView('sm');
            }
        },{
            enableToggle: true,
            allowDepress: false,
            toggleGroup: 'air2-drawer-controls',
            iconCls: 'air2-icon-bin-large',
            pressed: this.currView == 'lg',
            toggleHandler: function(btn, state) {
                if (state) this.transitionView('lg');
            }
        }],
        renderTo: this.el.child('.controls', true),
        clearBtns: function() {
            this.get(2).toggle(false);
            this.get(3).toggle(false);
        }
    });

    // setup some elements
    this.dBody = this.el.child('.body');
    this.dTab = this.el.child('.tab');
    if (initOpen) {
        this.dBody.setStyle('margin-bottom', '0px');
        this.el.removeClass('collapsed');
        this.el.addClass('expanded');
    }
    this.dView = this.dBody.child('.view');
    this.dView.setSize(this.sizes[this.currView]);

    // initialize infobar (used in single view)
    this.dInfo = this.el.child('.info');
    this.dInfo.setWidth(this.sizes[this.currView].width);

    // initialize toolbars
    this.tbarCt = this.dBody.child('.tbar');
    this.tbarCt.setWidth(this.sizes[this.currView].width);
    this.tbar = new AIR2.Drawer.Toolbar({
        inlineParams: (this.currView != 'si') ? inlineParams : null,
        renderTo: this.tbarCt,
        style: (this.sizes[this.currView].tbar) ? '' : 'display:none',
        startNewFn: this.createNew.createDelegate(this),
        deleteFn: this.deleteBin.createDelegate(this)
    });
    this.fbarCt = this.dBody.child('.fbar');
    this.fbarCt.setWidth(this.sizes[this.currView].width);
    this.fbar = new AIR2.Drawer.Footerbar({
        renderTo: this.fbarCt,
        style: (this.sizes[this.currView].fbar) ? '' : 'display:none',
        startNewFn: this.createNew.createDelegate(this),
        endNewFn: this.endNew.createDelegate(this)
    });

    // load the initial view
    this.views = {};
    var viewConfig = {
        renderTo: this.dView,
        inlineParams: inlineParams,
        inlineData: inlineData,
        inlineBin: inlineBin
    };
    if (this.currView == 'lg') {
        this.views.lg = new AIR2.Drawer.BinListLarge(viewConfig);
    }
    else if (this.currView == 'si') {
        viewConfig.infoEl = this.dInfo;
        viewConfig.infoWidth = this.sizes.si.width;
        this.views.si = new AIR2.Drawer.BinListSingle(viewConfig);
    }
    else { //default
        this.views.sm = new AIR2.Drawer.BinListSmall(viewConfig);
    }
    this.views[this.currView].el.unselectable();
    this.tbar.setView(this.currView, this.views[this.currView]);

    // event listeners
    this.el.first().unselectable(); //drawer tab
    this.el.on('click', function(e) {
        if (e.getTarget('.tab')) {
            this.isTmpOpen = false; //not a temp opening/shutting
            if (this.el.hasClass('collapsed')) {
                this.slideOpen();
            }
            else if (e.getTarget('.title')) {
                this.slideShut();
            }
        }
        else if (e.getTarget('.bin-expand')) {
            // get the bin record from the current view
            var el = e.getTarget(this.views[this.currView].itemSelector);
            var rec = this.views[this.currView].getRecord(el);
            this.lastvw = this.currView;
            this.transitionView('si', rec);
        }
    }, this);

    // setup content dropzone
    var drwr = this;
    this.dropZone = new Ext.dd.DropZone(this.dBody, {
        ddGroup: 'air2-drawer-ddzone',
        getTargetFromEvent: function(event) {
            var t = event.getTarget('.air2-drawer-batch');
            this.createMode = false;
            if (!t) {
                t = event.getTarget('.air2-drawer-create');
                if (t) this.createMode = true;
            }
            return t;
        },
        onNodeEnter: function(target, dd, e, data) {
            Ext.fly(target).addClass('hover');
            if (this.createMode) {
                this.hRec = null;
                this.hType = '?';
            }
            else {
                this.hRec = drwr.views[drwr.currView].getBinRecord(target);
                this.hType = (this.hRec.get('batch_owner')) ? this.hRec.get('batch_type') : null;
            }
        },
        onNodeOut: function(target, dd, e, data) {
            Ext.fly(target).removeClass('hover');
        },
        onNodeOver: function(target, dd, e, data) {
            if (this.hType == '?' || data.ddBatchType == this.hType)
                return Ext.dd.DropZone.prototype.dropAllowed;
            else
                return Ext.dd.DropZone.prototype.dropNotAllowed;
        },
        onNodeDrop: function(target, dd, e, data) {
            if (this.hType != '?' && data.ddBatchType != this.hType) {
                return false; // invalid drop
            }
            else if (!data.selections) {
                Logger("Error: no selection provided!");
                return false;
            }

            // determine if this drop will trigger a new batch
            if (this.createMode) {
                drwr.createNew(data.ddBatchType, data.selections);
            }
            else {
                drwr.views[drwr.currView].maskBin(target);
                var r = this.hRec, s = data.selections;
                AIR2.Drawer.API.addItems(r, s, function(data, success, counts) {
                    if (success) {
                        drwr.views[drwr.currView].refreshBin(target, counts);
                    }
                });
            }
            return true;
        }
    });
}
Ext.extend(AIR2.Drawer, Ext.Component, {
    id: 'air2-drawer',
    applyTo: 'air2-drawer',
    sizes: {
        sm: {width: 280, height: 226, tbar: false, fbar: true},
        lg: {width: 404, height: (Ext.getBody().getHeight() * .7), tbar: true, fbar: true},
        si: {width: 530, height: (Ext.getBody().getHeight() * .75) - 100, tbar: true, fbar: false}
    },
    refreshDDLocation: function() {
        //re-cache the DD-position of the drawer
        //Ext.dd.DragDropMgr.useCache = false; -- very inefficient
        var loc = Ext.dd.DragDropMgr.getLocation(this.dropZone);
        Ext.dd.DragDropMgr.locationCache[this.dropZone.id] = loc;
    },
    slideOpen: function() {
        var h = this.dBody.getHeight();
        this.el.removeClass('collapsed');
        this.dBody.animate({marginBottom: {from: -h, to: 0, unit: 'px'}}, .3,
            function() {
                if (!this.isTmpOpen) AIR2.Drawer.STATE.set('open', true);
                this.el.addClass('expanded');
                this.refreshDDLocation();
            }.createDelegate(this)
        );
    },
    slideShut: function() {
        var h = this.dBody.getHeight();
        this.el.removeClass('expanded');
        this.dBody.animate({marginBottom: {from: 0, to: -h, unit: 'px'}}, .3,
            function() {
                AIR2.Drawer.STATE.set('open', false);
                this.el.addClass('collapsed');
                this.dBody.setStyle('margin-bottom', '-9000px'); // WAY off the page
            }.createDelegate(this)
        );
    },
    tempOpen: function() {
        if (!this.isTmpOpen && this.el.hasClass('collapsed')) {
            this.isTmpOpen = true;
            this.slideOpen();
        }
    },
    tempShut: function() {
        if (this.isTmpOpen && this.el.hasClass('expanded')) {
            this.isTmpOpen = false;
            new Ext.util.DelayedTask(this.slideShut, this).delay(1000);
        }
    },
    resizeBody: function(newView, noAnimation) {
        var dur = (noAnimation) ? 0 : .3;
        this.dView.scale(
            this.sizes[newView].width,
            this.sizes[newView].height,
            {duration: dur, callback: function() {
                this.views[newView].el.fadeIn({duration:.1});
            }.createDelegate(this)}
        );
        this.dInfo.setWidth(this.sizes[newView].width, {duration: dur});
        this.tbarCt.setWidth(this.sizes[newView].width, {duration: dur});
        this.fbarCt.setWidth(this.sizes[newView].width, {duration: dur});
    },
    redrawToolbars: function(newView, noAnimation) {
        this.tbar.setView(newView, this.views[newView]); //refresh the toolbar items

        var dur = (noAnimation) ? 0 : .3;
        if (this.sizes[newView].tbar && !this.tbar.isVisible()) {
            this.tbar.el.slideIn('t', {duration: dur, useDisplay: true});
        }
        else if (!this.sizes[newView].tbar && this.tbar.isVisible()) {
            this.tbar.el.slideOut('t', {duration: dur, useDisplay: true});
        }
        if (this.sizes[newView].fbar && !this.fbar.isVisible()) {
            this.fbar.el.slideIn('b', {duration: dur, useDisplay: true});
        }
        else if (!this.sizes[newView].fbar && this.fbar.isVisible()) {
            this.fbar.el.slideOut('b', {duration: dur, useDisplay: true});
        }
    },
    transitionView: function(changeTo, binRec) {
        if (!this.views[changeTo]) {
            var config = {
                renderTo: this.dView,
                style: 'visibility: hidden'
            };
            if (changeTo == 'sm')
                this.views[changeTo] = new AIR2.Drawer.BinListSmall(config);
            else if (changeTo == 'lg')
                this.views[changeTo] = new AIR2.Drawer.BinListLarge(config);
            else if (changeTo == 'si') {
                this.controls.clearBtns(); // unselect controls
                config.binRec = binRec;
                config.infoEl = this.dInfo;
                config.infoWidth = this.sizes.si.width;
                this.views[changeTo] = new AIR2.Drawer.BinListSingle(config);
            }
        }
        else {
            if (changeTo == 'si') {
                this.controls.clearBtns(); // unselect controls
                this.views.si.setRecord(binRec);
            }
            this.views[changeTo].reloadDataView(true);
        }

        // reset the toolbars, if applicable
        this.redrawToolbars(changeTo);

        // transition the current and new views
        if (this.currView == 'si') this.views.si.hideInfo(); //hide infobar
        this.views[this.currView].el.fadeOut({duration:.1, useDisplay:true});
        this.resizeBody(changeTo);

        // set the current view
        this.currView = changeTo;
        this.views[this.currView].el.unselectable();
        AIR2.Drawer.STATE.set('view', changeTo);
    },
    createNew: function(type, addRecs, mergeRecs) {
        var old = this.views[this.currView];

        // create a unique bin name --- use username and timestamp
        var dt = new Date();
        var newRec = new old.store.recordType({
            batch_name: AIR2.USERNAME + ' ' + dt.format('Y-m-d H:i:s'),
            batch_type: type || 'S',
            batch_public_flag: false
        });
        var formTitle = 'Create New Bin';
        if (mergeRecs && mergeRecs.length > 1)
            formTitle = 'Create Merged Bin';
        else if (mergeRecs && mergeRecs.length == 1) {
            formTitle = 'Create Duplicate Bin';
        }

        if (!this.createBinForm) {
            this.createBinForm = new Ext.form.FormPanel({
                cls: 'air2-create-new',
                renderTo: this.dView,
                style: 'display:none',
                unstyled: true,
                labelWidth: 75,
                items: [{
                    xtype: 'label',
                    cls: 'create-new-title',
                    html: '<h1>'+formTitle+'</h1>'
                },{
                    xtype: 'air2remotetext',
                    fieldLabel: 'Bin Name',
                    name: 'batch_name',
                    width: '96%',
                    allowBlank: false,
                    remoteUrl: AIR2.HOMEURL + '/batch/name.json'
                },{
                    xtype: 'textarea',
                    fieldLabel: 'Description',
                    name: 'batch_desc',
                    width: '96%',
                    maxLength: 256
                },{
                    xtype: 'hidden',
                    name: 'batch_type',
                    value: 'S' // source batch
                },{
                    xtype: 'combo',
                    fieldLabel: 'Shared',
                    name: 'batch_public_flag',
                    width: 100,
                    mode: 'local',
                    store: new Ext.data.ArrayStore({
                        id: 0,
                        fields: ['value', 'display'],
                        data: [[false, 'No'], [true, 'Yes']]
                    }),
                    valueField: 'value',
                    displayField: 'display',
                    triggerAction: 'all',
                    forceSelection: true,
                    editable: false
                }]
            });
        }
        else {
            this.createBinForm.get(0).update('<h1>'+formTitle+'</h1>');
            this.createBinForm.get(3).setDisabled((type) ? true : false);
        }

        old.el.fadeOut({duration:.1, useDisplay:true});
        this.tbar.el.slideOut('t', {duration: .1, useDisplay: true});
        this.fbar.setNewMode(true);
        var f = this.createBinForm;
        this.dView.scale(330, 230, {
            duration: .3,
            callback: function() {
                f.el.fadeIn({duration:.1, useDisplay:true});
                f.getForm().loadRecord(newRec);
                f.get(1).focus(true);
            }
        });
        this.dInfo.setWidth(1);
        this.tbarCt.setWidth(330, {duration: .3});
        this.fbarCt.setWidth(330, {duration: .3});

        // disable the tab
        this.dTab.setStyle('opacity', .6);
        this.controls.disable();

        //setup the references for "endNew" to use
        this.newRec = newRec;
        this.newAdd = addRecs;
        this.newMerge = mergeRecs;
    },
    endNew: function(doSave) {
        if (doSave) {
            var store = this.views[this.currView].store;
            if (!this.createBinForm.getForm().isValid()) return;
            this.createBinForm.getForm().updateRecord(this.newRec);
            this.createBinForm.el.mask('Saving');
            store.insert(0, this.newRec);

            // save the record, and add any selections/merges afterwards
            store.on('save', function() {
                var restore = function() {
                    this.endNew(false);
                    this.views[this.currView].reloadDataView();
                }.createDelegate(this);

                if (this.newAdd) {
                    var ar = this.newRec, a = this.newAdd;
                    AIR2.Drawer.API.addItems(ar, a, function(data, success) {
                        restore();
                    });
                }
                else if (this.newMerge) {
                    var mr = this.newRec, m = this.newMerge;
                    AIR2.Drawer.API.merge(mr, m, function(data, success) {
                        restore();
                    });
                }
                else {
                    restore();
                }
            }, this, {single:true});
            store.save();
        }
        else {
            var el = this.createBinForm.el;
            el.fadeOut({duration:.1, useDisplay:true, callback:function() {el.unmask();}});
            this.fbar.setNewMode(false);
            this.dTab.setStyle('opacity', 1);
            this.controls.enable();
            this.resizeBody(this.currView);
            this.redrawToolbars(this.currView);

            //unreference
            this.newRec = false;
            this.newAdd = false;
            this.newMerge = false;
        }
    },
    deleteBin: function(recs) {
        var r = recs[0], s = this.views[this.currView].store, b = this.dBody;
        var msg = 'Delete bin "' + r.get('batch_name') +'"?';
        var d = b.createChild({
            tag: 'div',
            cls: 'delete-prompt air2-corners',
            html: '<div class="dbody">' +
                    '<div class="msg">' + msg + '</div>' +
                    '<div class="buttons">' +
                      '<span class="air2-btn air2-btn-delete air2-btn-medium">' +
                        '<button class="x-btn-text">Delete</button>' +
                      '</span> ' +
                      '<span class="air2-btn air2-btn-cancel air2-btn-medium">' +
                        '<button class="x-btn-text">Cancel</button>' +
                      '</span>' +
                    '</div>' +
                  '</div>'
        });
        d.on('click', function(e) {
            if (e.getTarget('.air2-btn-delete')) {
                s.remove(r);
                s.save();
                b.unmask();
                d.ghost('b', {remove:true});
            }
            else if (e.getTarget('.air2-btn-cancel')) {
                b.unmask();
                d.slideOut('t', {remove:true});
            }
        });
        b.mask();
        d.slideIn('t');
    }
});